﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Framework.Infrastructure;
using Framework.Config;
using System.Messaging;
using System.Threading;
using Framework.Bus.LifetimeManagers;

namespace Framework.Bus.MsmqServiceBus
{
    public class MessageHandler : TaskWorker
    {
        IMessageDispatcher _messageDispatcher;
        EndpointElement _endpointElement;
        protected MessageQueue _messageQueue;

        public MessageHandler(IMessageDispatcher messageDispatcher, EndpointElement endpointElement)
        {
            _messageDispatcher = messageDispatcher;
            _endpointElement = endpointElement;
            try
            {
                _messageQueue = new MessageQueue(endpointElement.Endpoint, false, false, QueueAccessMode.SendAndReceive);
                _messageQueue.Formatter = new BinaryMessageFormatter(System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full,
                System.Runtime.Serialization.Formatters.FormatterTypeStyle.TypesAlways);
                _messageQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(_messageQueue_ReceiveCompleted);
            }
            catch (System.Exception ex)
            {
                Console.Write(ex.Message);
            }
        }

        protected override void Work()
        {
            try
            {
                ReveiveProcess();
            }
            catch (System.Exception)
            {

            }
        }

        public override void Stop(bool forcibly = false)
        {
            base.Stop(forcibly);
            _messageQueue.Close();
        }

        protected virtual void _messageQueue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs asyncResult)
        {
            if (_toExit)
            {
                return;
            }
            try
            {
                MessageQueue mq = (MessageQueue)sender;
                // End the asynchronous receive operation.

                Message message = mq.EndReceive(asyncResult.AsyncResult);
                ProcessMessage(message);
            }
            catch (System.Exception ex)
            {
                Console.Write(ex.Message);
            }

        }

        protected virtual void ProcessMessage(Message message)
        {
            if (message != null)
            {
                message.Formatter = _messageQueue.Formatter;
                PerMessageContextLifetimeManager.InitCaches();
                _messageDispatcher.DispatchMessage(message.Body);
                PerMessageContextLifetimeManager.ClearCaches();
            }
        }

        protected virtual void PeekProcess()
        {
            var waitHandle = _messageQueue.BeginPeek();
            waitHandle.AsyncWaitHandle.WaitOne();
        }

        protected virtual void ReveiveProcess()
        {
            var waitHandle = _messageQueue.BeginReceive();
            waitHandle.AsyncWaitHandle.WaitOne();
        }

    }
}
